#ifndef _COMM_HPP_
#define _COMM_HPP_

#include <iostream>
#include <stdio.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PATHNAME "."
#define PROJ_ID  0x345
//共享内存的大小，一般建议是4KB的整数倍
//系统分配共享内存是以4KB为单位！----内存划分内存块的基本单位Page
//内核会给你向上取整  4097 ---4KB*2  内核给你的和你能用的是两码事。
//虽然给了你4096*2的内存，但是你只能用4097
#define MAX_SIZE 4096

key_t Getftok(const char* pathname,int id)
{
    key_t k= ftok(PATHNAME, PROJ_ID); //可以获取同一个KEY！！
    if(k<0)
    {
        // cin, cout, cerr -> stdin, stdout, stderr -> 0, 1, 2
        std::cerr << errno << ":" << strerror(errno) << std::endl;
        exit(1);  //退出错误码
    }
    return k;
}


int ShmHelper(key_t key,int mode)
{
    // key是shmget，设置进入共享内存属性中的！！！
    //用来表示该共享内存再内核中的唯一性！！
    int shmid = shmget(key,MAX_SIZE,mode); 
    if(shmid<0)
    {
        std::cerr<<errno<<":"<<strerror(errno)<<std::endl;
        exit(2);
    }
    return shmid;
}
//创建共享内存
int CreateShm(key_t key)
{
    return ShmHelper(key,IPC_CREAT|IPC_EXCL|0666); //注意这里的0x666必须传，文件的权限，如果时0的画，就不能对共享内存文件进行操作
}
//获得贡献内存的shmid值
int GetShm(key_t key)
{
    return ShmHelper(key,IPC_CREAT);
}
//让进程和shmid关联
void* AttachShm(int shmid)
{
    void* start = shmat(shmid,nullptr,0); //再Linux系统中，是64位的系统，所以指针的大小是8字节
    //如果与int 4字节相比的话，会有精度缺失
    if((long long)start == -1L)
    {
        std::cerr<<errno<<":"<<strerror(errno)<<std::endl;
        exit(3);
    }
    return start;
}
//去关联
void DtachShm(void* shmaddr)
{
    
    if(shmdt(shmaddr) == -1 )
    {
        std::cerr<<"DtachShm"<<errno<<":"<<strerror(errno)<<std::endl;
    }
}
//删除共享资源块
void Delshm(int shmid)
{
    if(shmctl(shmid,IPC_RMID,nullptr)==-1)
    {
        std::cerr<<errno<<":"<<strerror(errno)<<std::endl;
    }
}

#endif

